// main.vala - Main Window, Command Center, History & Options for Tech HUD Starter
using Gtk;
using Cairo;
using GLib;

public class TechHudHistoryEditDialog : Gtk.Dialog {
    private Gtk.TextView text_view;
    private TechHudStarterWindow parent_win;

    public TechHudHistoryEditDialog (TechHudStarterWindow parent_win) {
        Object (title: _("Edit Command History"), transient_for: parent_win, modal: true);
        this.set_default_size (500, 450);
        this.parent_win = parent_win;

        var content = this.get_content_area () as Gtk.Box;
        content.margin = 15;
        content.spacing = 10;

        var info_label = new Gtk.Label (_("Edit history commands below (one command per line). Duplicate lines will be filtered automatically on save:"));
        info_label.set_line_wrap (true);
        content.pack_start (info_label, false, false, 0);

        text_view = new Gtk.TextView ();
        text_view.set_monospace (true);
        var buffer = text_view.get_buffer ();

        string full_history = string.joinv ("\n", parent_win.get_history_array ());
        buffer.set_text (full_history);

        var scrolled = new Gtk.ScrolledWindow (null, null);
        scrolled.set_shadow_type (Gtk.ShadowType.IN);
        scrolled.set_vexpand (true);
        scrolled.add (text_view);
        content.pack_start (scrolled, true, true, 0);

        var btn_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 10);
        btn_box.set_halign (Gtk.Align.END);

        var cancel_btn = new Gtk.Button.with_label (_("Cancel"));
        cancel_btn.clicked.connect (() => {
            this.destroy ();
        });

        var save_btn = new Gtk.Button.with_label (_("Save & Apply"));
        save_btn.get_style_context ().add_class ("suggested-action");
        save_btn.clicked.connect (() => {
            Gtk.TextIter start, end;
            buffer.get_start_iter (out start);
            buffer.get_end_iter (out end);
            string text = buffer.get_text (start, end, false);

            parent_win.set_history_from_text (text);
            this.destroy ();
        });

        btn_box.pack_start (cancel_btn, false, false, 0);
        btn_box.pack_start (save_btn, false, false, 0);
        content.pack_start (btn_box, false, false, 0);

        this.show_all ();
    }
}

public class TechHudStarterOptionsDialog : Gtk.Dialog {
    public TechHudStarterOptionsDialog (TechHudStarterWindow parent_win) {
        Object (title: _("Tech HUD Starter - Advanced Settings"), transient_for: parent_win, modal: true);
        this.set_default_size (540, 750);

        var content = this.get_content_area () as Gtk.Box;
        content.margin = 15;
        content.spacing = 10;

        var notebook = new Gtk.Notebook ();
        content.pack_start (notebook, true, true, 0);
        // Opacity rows inline
// TAB 1: Panel Appearance
        var app_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10); app_box.margin = 12;
        var app_scroll = new Gtk.ScrolledWindow (null, null); app_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); app_scroll.add (app_box);

        var theme_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        theme_box.pack_start (new Gtk.Label (_("Color Theme:")), false, false, 0);
        var theme_combo = new Gtk.ComboBoxText ();
        for (int i = 0; i < ThemeManager.get_theme_count (); i++) {
            theme_combo.append_text (ThemeManager.get_theme (i).name);
        }
        theme_combo.active = parent_win.theme_index;
        theme_combo.changed.connect (() => {
            if (theme_combo.active != -1) {
                parent_win.theme_index = theme_combo.active;
                parent_win.apply_and_save ();
            }
        });
        theme_box.pack_end (theme_combo, false, false, 0);
        app_box.pack_start (theme_box, false, false, 0);

        var border_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        border_box.pack_start (new Gtk.Label (_("Panel Border Style:")), false, false, 0);
        var border_combo = new Gtk.ComboBoxText ();
        string[] border_style_names = {
            _("0: Classic HUD Box"), _("1: Top-Notch Header"), _("2: Slanted Vent"),
            _("3: Compact Square"), _("4: Double-Notched"), _("5: Armored Hex"),
            _("6: Right Hatch (compact)"), _("7: Dual Gills (compact)"), _("8: Armored Capsule (compact)")
        };
        for (int i = 0; i < border_style_names.length; i++) {
            border_combo.append_text (border_style_names[i]);
        }
        border_combo.active = parent_win.border_style;
        border_combo.changed.connect (() => {
            if (border_combo.active != -1) {
                parent_win.border_style = border_combo.active;
                parent_win.apply_and_save ();
            }
        });
        border_box.pack_end (border_combo, false, false, 0);
        app_box.pack_start (border_box, false, false, 0);

        var design_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        design_box.pack_start (new Gtk.Label (_("Panel Design Category:")), false, false, 0);
        var design_combo = new Gtk.ComboBoxText ();
        design_combo.append_text (_("0: Starship-Neon (Classic)"));
        design_combo.append_text (_("1: Glass"));
        design_combo.append_text (_("2: Marble"));
        design_combo.active = parent_win.design_category;
        design_box.pack_end (design_combo, false, false, 0);
        app_box.pack_start (design_box, false, false, 0);

        var glass_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        glass_box.pack_start (new Gtk.Label (_("Panel Glass Variant:")), false, false, 0);
        var glass_combo = new Gtk.ComboBoxText ();
        glass_combo.append_text (_("0: Clear"));
        glass_combo.append_text (_("1: Frosted"));
        glass_combo.append_text (_("2: Blurry"));
        glass_combo.append_text (_("3: Ultra-Clear"));
        glass_combo.append_text (_("4: Diamond"));
        glass_combo.active = parent_win.glass_variant;
        glass_box.pack_end (glass_combo, false, false, 0);
        glass_box.sensitive = (parent_win.design_category == 1);
        app_box.pack_start (glass_box, false, false, 0);

        design_combo.changed.connect (() => {
            if (design_combo.active != -1) {
                parent_win.design_category = design_combo.active;
                glass_box.sensitive = (parent_win.design_category == 1);
                parent_win.apply_and_save ();
            }
        });
        glass_combo.changed.connect (() => {
            if (glass_combo.active != -1) {
                parent_win.glass_variant = glass_combo.active;
                parent_win.apply_and_save ();
            }
        });

        var bg_op_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        bg_op_box.pack_start (new Gtk.Label (_("Panel Background Opacity:")), false, false, 0);
        var bg_spin = new SpinButton.with_range (0.1, 1.0, 0.05); bg_spin.value = parent_win.bg_opacity; bg_spin.digits = 2;
        bg_spin.value_changed.connect (() => { parent_win.bg_opacity = bg_spin.value; parent_win.apply_and_save (); });
        bg_op_box.pack_end (bg_spin, false, false, 0); app_box.pack_start (bg_op_box, false, false, 0);

        notebook.append_page (app_scroll, new Gtk.Label (_("Panel")));

        // TAB 2: Element Appearance (Buttons, Entry, Text displays)
        var elem_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10); elem_box.margin = 12;
        var elem_scroll = new Gtk.ScrolledWindow (null, null); elem_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); elem_scroll.add (elem_box);

        var elem_design_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        elem_design_box.pack_start (new Gtk.Label (_("Element Design Category:")), false, false, 0);
        var elem_design_combo = new Gtk.ComboBoxText ();
        elem_design_combo.append_text (_("0: Starship-Neon (Classic)"));
        elem_design_combo.append_text (_("1: Glass"));
        elem_design_combo.append_text (_("2: Marble"));
        elem_design_combo.active = parent_win.element_design_category;
        elem_design_box.pack_end (elem_design_combo, false, false, 0);
        elem_box.pack_start (elem_design_box, false, false, 0);

        var elem_glass_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        elem_glass_box.pack_start (new Gtk.Label (_("Element Glass Variant:")), false, false, 0);
        var elem_glass_combo = new Gtk.ComboBoxText ();
        elem_glass_combo.append_text (_("0: Clear"));
        elem_glass_combo.append_text (_("1: Frosted"));
        elem_glass_combo.append_text (_("2: Blurry"));
        elem_glass_combo.append_text (_("3: Ultra-Clear"));
        elem_glass_combo.append_text (_("4: Diamond"));
        elem_glass_combo.active = parent_win.element_glass_variant;
        elem_glass_box.pack_end (elem_glass_combo, false, false, 0);
        elem_glass_box.sensitive = (parent_win.element_design_category == 1);
        elem_box.pack_start (elem_glass_box, false, false, 0);

        elem_design_combo.changed.connect (() => {
            if (elem_design_combo.active != -1) {
                parent_win.element_design_category = elem_design_combo.active;
                elem_glass_box.sensitive = (parent_win.element_design_category == 1);
                parent_win.apply_and_save ();
            }
        });
        elem_glass_combo.changed.connect (() => {
            if (elem_glass_combo.active != -1) {
                parent_win.element_glass_variant = elem_glass_combo.active;
                parent_win.apply_and_save ();
            }
        });

        notebook.append_page (elem_scroll, new Gtk.Label (_("Elements")));

        // TAB 3: Text & Effects
        var text_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10); text_box.margin = 12;
        var text_scroll = new Gtk.ScrolledWindow (null, null); text_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); text_scroll.add (text_box);

        var text3d_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        text3d_box.pack_start (new Gtk.Label (_("Text 3D Style:")), false, false, 0);
        var text3d_combo = new Gtk.ComboBoxText ();
        text3d_combo.append_text (_("0: Normal"));
        text3d_combo.append_text (_("1: Debossed / Carved"));
        text3d_combo.append_text (_("2: Embossed / Raised"));
        text3d_combo.active = parent_win.text_3d_style;
        text3d_combo.changed.connect (() => {
            if (text3d_combo.active != -1) {
                parent_win.text_3d_style = text3d_combo.active;
                parent_win.apply_and_save ();
            }
        });
        text3d_box.pack_end (text3d_combo, false, false, 0);
        text_box.pack_start (text3d_box, false, false, 0);

        var shadow_check = new Gtk.CheckButton.with_label (_("Use Text Shadow Effect"));
        shadow_check.active = parent_win.use_text_shadow;
        text_box.pack_start (shadow_check, false, false, 0);

        var shadow_style_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        shadow_style_box.pack_start (new Gtk.Label (_("Shadow Style:")), false, false, 0);
        var shadow_style_combo = new Gtk.ComboBoxText ();
        shadow_style_combo.append_text (_("0: Soft Double Shadow"));
        shadow_style_combo.append_text (_("1: Hard Shadow"));
        shadow_style_combo.append_text (_("2: Glow + Shadow"));
        shadow_style_combo.active = parent_win.text_shadow_style;
        shadow_style_box.pack_end (shadow_style_combo, false, false, 0);
        shadow_style_box.sensitive = parent_win.use_text_shadow;
        text_box.pack_start (shadow_style_box, false, false, 0);

        shadow_check.toggled.connect (() => {
            parent_win.use_text_shadow = shadow_check.active;
            shadow_style_box.sensitive = parent_win.use_text_shadow;
            parent_win.apply_and_save ();
        });
        shadow_style_combo.changed.connect (() => {
            if (shadow_style_combo.active != -1) {
                parent_win.text_shadow_style = shadow_style_combo.active;
                parent_win.apply_and_save ();
            }
        });

        var border_frame = new Gtk.Frame (_("Border Color"));
        var border_inner = new Gtk.Box (Gtk.Orientation.VERTICAL, 8); border_inner.margin = 10; border_frame.add (border_inner);
        var use_custom_border_check = new Gtk.CheckButton.with_label (_("Use Custom Border Color"));
        use_custom_border_check.active = parent_win.use_custom_border;
        border_inner.pack_start (use_custom_border_check, false, false, 0);
        var border_color_row = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 10);
        border_color_row.pack_start (new Gtk.Label (_("Custom Border Color:")), false, false, 0);
        var border_color_btn = new Gtk.ColorButton ();
        Gdk.RGBA b_rgba = Gdk.RGBA (); b_rgba.red = (float)parent_win.custom_border_r; b_rgba.green = (float)parent_win.custom_border_g; b_rgba.blue = (float)parent_win.custom_border_b; b_rgba.alpha = 1.0f;
        border_color_btn.rgba = b_rgba;
        border_color_row.pack_start (border_color_btn, false, false, 0);
        border_inner.pack_start (border_color_row, false, false, 0);
        border_color_btn.sensitive = parent_win.use_custom_border;
        text_box.pack_start (border_frame, false, false, 0);

        use_custom_border_check.toggled.connect (() => {
            parent_win.use_custom_border = use_custom_border_check.active;
            border_color_btn.sensitive = parent_win.use_custom_border;
            parent_win.apply_and_save ();
        });
        border_color_btn.color_set.connect (() => {
            Gdk.RGBA col = border_color_btn.rgba;
            parent_win.custom_border_r = col.red; parent_win.custom_border_g = col.green; parent_win.custom_border_b = col.blue;
            parent_win.apply_and_save ();
        });

        var primary_frame = new Gtk.Frame (_("Primary Text Color"));
        var primary_inner = new Gtk.Box (Gtk.Orientation.VERTICAL, 8); primary_inner.margin = 10; primary_frame.add (primary_inner);
        var primary_radio_border = new Gtk.RadioButton.with_label (null, _("Use Border Color for Primary"));
        var primary_radio_custom = new Gtk.RadioButton.with_label_from_widget (primary_radio_border, _("Use Color Dialog for Primary"));
        primary_radio_border.active = parent_win.use_border_for_primary;
        primary_radio_custom.active = !parent_win.use_border_for_primary;
        primary_inner.pack_start (primary_radio_border, false, false, 0);
        primary_inner.pack_start (primary_radio_custom, false, false, 0);
        var primary_color_row = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 10);
        primary_color_row.pack_start (new Gtk.Label (_("Custom Primary Text Color:")), false, false, 0);
        var primary_color_btn = new Gtk.ColorButton ();
        Gdk.RGBA p_rgba = Gdk.RGBA (); p_rgba.red = (float)parent_win.custom_primary_r; p_rgba.green = (float)parent_win.custom_primary_g; p_rgba.blue = (float)parent_win.custom_primary_b; p_rgba.alpha = 1.0f;
        primary_color_btn.rgba = p_rgba;
        primary_color_row.pack_start (primary_color_btn, false, false, 0);
        primary_inner.pack_start (primary_color_row, false, false, 0);
        primary_color_btn.sensitive = !parent_win.use_border_for_primary;
        text_box.pack_start (primary_frame, false, false, 0);

        primary_radio_border.toggled.connect (() => {
            if (primary_radio_border.active) { parent_win.use_border_for_primary = true; primary_color_btn.sensitive = false; parent_win.apply_and_save (); }
        });
        primary_radio_custom.toggled.connect (() => {
            if (primary_radio_custom.active) { parent_win.use_border_for_primary = false; primary_color_btn.sensitive = true; parent_win.apply_and_save (); }
        });
        primary_color_btn.color_set.connect (() => {
            Gdk.RGBA col = primary_color_btn.rgba; parent_win.custom_primary_r = col.red; parent_win.custom_primary_g = col.green; parent_win.custom_primary_b = col.blue;
            parent_win.apply_and_save ();
        });

        notebook.append_page (text_scroll, new Gtk.Label (_("Text & Colors")));

        // TAB 5: Opacities (using Gtk.Scale sliders)
        var opacity_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10); opacity_box.margin = 12;
        var opacity_scroll = new Gtk.ScrolledWindow (null, null); opacity_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); opacity_scroll.add (opacity_box);

        Gtk.Scale bg_scale, txt_scale, brd_scale, elem_bg_scale, elem_brd_scale;

        var bg_row = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        bg_row.pack_start (new Gtk.Label (_("Background Opacity %:")), false, false, 0);
        bg_scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);
        bg_scale.set_value (parent_win.bg_opacity * 100.0); bg_scale.digits = 0; bg_scale.draw_value = true; bg_scale.value_pos = Gtk.PositionType.RIGHT; bg_scale.hexpand = true;
        bg_row.pack_start (bg_scale, true, true, 0);
        bg_scale.value_changed.connect (() => { parent_win.bg_opacity = bg_scale.get_value () / 100.0; parent_win.apply_and_save (); });
        opacity_box.pack_start (bg_row, false, false, 0);

        var txt_row = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        txt_row.pack_start (new Gtk.Label (_("Text Opacity %:")), false, false, 0);
        txt_scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);
        txt_scale.set_value (parent_win.text_opacity * 100.0); txt_scale.digits = 0; txt_scale.draw_value = true; txt_scale.value_pos = Gtk.PositionType.RIGHT; txt_scale.hexpand = true;
        txt_row.pack_start (txt_scale, true, true, 0);
        txt_scale.value_changed.connect (() => { parent_win.text_opacity = txt_scale.get_value () / 100.0; parent_win.apply_and_save (); });
        opacity_box.pack_start (txt_row, false, false, 0);

        var brd_row = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        brd_row.pack_start (new Gtk.Label (_("Border Opacity %:")), false, false, 0);
        brd_scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);
        brd_scale.set_value (parent_win.border_opacity * 100.0); brd_scale.digits = 0; brd_scale.draw_value = true; brd_scale.value_pos = Gtk.PositionType.RIGHT; brd_scale.hexpand = true;
        brd_row.pack_start (brd_scale, true, true, 0);
        brd_scale.value_changed.connect (() => { parent_win.border_opacity = brd_scale.get_value () / 100.0; parent_win.apply_and_save (); });
        opacity_box.pack_start (brd_row, false, false, 0);

        var elem_bg_row = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        elem_bg_row.pack_start (new Gtk.Label (_("Element Background Opacity %:")), false, false, 0);
        elem_bg_scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);
        elem_bg_scale.set_value (parent_win.element_bg_opacity * 100.0); elem_bg_scale.digits = 0; elem_bg_scale.draw_value = true; elem_bg_scale.value_pos = Gtk.PositionType.RIGHT; elem_bg_scale.hexpand = true;
        elem_bg_row.pack_start (elem_bg_scale, true, true, 0);
        elem_bg_scale.value_changed.connect (() => { parent_win.element_bg_opacity = elem_bg_scale.get_value () / 100.0; parent_win.apply_and_save (); });
        opacity_box.pack_start (elem_bg_row, false, false, 0);

        var elem_brd_row = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        elem_brd_row.pack_start (new Gtk.Label (_("Element Border Opacity %:")), false, false, 0);
        elem_brd_scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);
        elem_brd_scale.set_value (parent_win.element_border_opacity * 100.0); elem_brd_scale.digits = 0; elem_brd_scale.draw_value = true; elem_brd_scale.value_pos = Gtk.PositionType.RIGHT; elem_brd_scale.hexpand = true;
        elem_brd_row.pack_start (elem_brd_scale, true, true, 0);
        elem_brd_scale.value_changed.connect (() => { parent_win.element_border_opacity = elem_brd_scale.get_value () / 100.0; parent_win.apply_and_save (); });
        opacity_box.pack_start (elem_brd_row, false, false, 0);

        notebook.append_page (opacity_scroll, new Gtk.Label (_("Opacities")));

        // TAB 6: Window & Sizes
        var window_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10); window_box.margin = 12;
        var window_scroll = new Gtk.ScrolledWindow (null, null); window_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); window_scroll.add (window_box);

        var scale_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        scale_box.pack_start (new Gtk.Label (_("UI Scale Factor (Layout):")), false, false, 0);
        var spin = new SpinButton.with_range (0.5, 2.5, 0.1); spin.value = parent_win.ui_scale; spin.digits = 2;
        spin.value_changed.connect (() => { parent_win.ui_scale = spin.value; parent_win.apply_and_save (); });
        scale_box.pack_end (spin, false, false, 0); window_box.pack_start (scale_box, false, false, 0);

        var text_scale_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        text_scale_box.pack_start (new Gtk.Label (_("Text Scale (independent):")), false, false, 0);
        var text_spin = new SpinButton.with_range (0.5, 3.0, 0.1); text_spin.value = parent_win.text_scale; text_spin.digits = 2;
        text_spin.value_changed.connect (() => { parent_win.text_scale = text_spin.value; parent_win.apply_and_save (); });
        text_scale_box.pack_end (text_spin, false, false, 0); window_box.pack_start (text_scale_box, false, false, 0);

        var pos_x_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        pos_x_box.pack_start (new Gtk.Label (_("Window Position X:")), false, false, 0);
        var pos_x_spin = new SpinButton.with_range (-3000, 5000, 10); pos_x_spin.value = parent_win.saved_pos_x;
        pos_x_spin.value_changed.connect (() => { parent_win.saved_pos_x = (int)pos_x_spin.value; parent_win.has_saved_position = true; parent_win.move (parent_win.saved_pos_x, parent_win.saved_pos_y); parent_win.save_config (); });
        pos_x_box.pack_end (pos_x_spin, false, false, 0); window_box.pack_start (pos_x_box, false, false, 0);

        var pos_y_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        pos_y_box.pack_start (new Gtk.Label (_("Window Position Y:")), false, false, 0);
        var pos_y_spin = new SpinButton.with_range (-3000, 5000, 10); pos_y_spin.value = parent_win.saved_pos_y;
        pos_y_spin.value_changed.connect (() => { parent_win.saved_pos_y = (int)pos_y_spin.value; parent_win.has_saved_position = true; parent_win.move (parent_win.saved_pos_x, parent_win.saved_pos_y); parent_win.save_config (); });
        pos_y_box.pack_end (pos_y_spin, false, false, 0); window_box.pack_start (pos_y_box, false, false, 0);

        int cur_w, cur_h; parent_win.get_size (out cur_w, out cur_h);

        var width_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        width_box.pack_start (new Gtk.Label (_("Window Width:")), false, false, 0);
        var width_spin = new SpinButton.with_range (200, 3000, 10); width_spin.value = cur_w;
        width_spin.value_changed.connect (() => { int cw, ch; parent_win.get_size (out cw, out ch); parent_win.window_width = (int)width_spin.value; parent_win.resize (parent_win.window_width, ch); parent_win.save_config (); });
        width_box.pack_end (width_spin, false, false, 0); window_box.pack_start (width_box, false, false, 0);

        var height_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        height_box.pack_start (new Gtk.Label (_("Window Height:")), false, false, 0);
        var height_spin = new SpinButton.with_range (150, 3000, 10); height_spin.value = cur_h;
        height_spin.value_changed.connect (() => { int cw, ch; parent_win.get_size (out cw, out ch); parent_win.window_height = (int)height_spin.value; parent_win.resize (cw, parent_win.window_height); parent_win.save_config (); });
        height_box.pack_end (height_spin, false, false, 0); window_box.pack_start (height_box, false, false, 0);

        var hint_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        hint_box.pack_start (new Gtk.Label (_("Window Type Hint:")), false, false, 0);
        var hint_combo = new Gtk.ComboBoxText (); hint_combo.append_text (_("Normal (Default)")); hint_combo.append_text (_("Utility")); hint_combo.append_text (_("Dock")); hint_combo.active = parent_win.window_type_hint_mode;
        hint_combo.changed.connect (() => { if (hint_combo.active != -1) { parent_win.window_type_hint_mode = hint_combo.active; parent_win.apply_and_save (); } });
        hint_box.pack_end (hint_combo, false, false, 0); window_box.pack_start (hint_box, false, false, 0);

        var layer_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        layer_box.pack_start (new Gtk.Label (_("Window Layer:")), false, false, 0);
        var layer_combo = new Gtk.ComboBoxText (); layer_combo.append_text (_("Normal")); layer_combo.append_text (_("Above (Keep Above)")); layer_combo.append_text (_("Below (Wallpaper glass)"));
        if (parent_win.window_layer == "above") layer_combo.active = 1; else if (parent_win.window_layer == "below") layer_combo.active = 2; else layer_combo.active = 0;
        layer_combo.changed.connect (() => { if (layer_combo.active == 1) parent_win.window_layer = "above"; else if (layer_combo.active == 2) parent_win.window_layer = "below"; else parent_win.window_layer = "normal"; parent_win.apply_and_save (); });
        layer_box.pack_end (layer_combo, false, false, 0); window_box.pack_start (layer_box, false, false, 0);

        var sticky_check = new Gtk.CheckButton.with_label (_("Sticky across workspaces")); sticky_check.active = parent_win.window_sticky;
        sticky_check.toggled.connect (() => { parent_win.window_sticky = sticky_check.active; parent_win.apply_and_save (); });
        window_box.pack_start (sticky_check, false, false, 0);

        var hist_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12);
        hist_box.pack_start (new Gtk.Label (_("Command History Management:")), false, false, 0);
        var edit_hist_btn = new Gtk.Button.with_label (_("Edit History..."));
        edit_hist_btn.clicked.connect (() => { var hist_dlg = new TechHudHistoryEditDialog (parent_win); hist_dlg.run (); hist_dlg.destroy (); });
        hist_box.pack_end (edit_hist_btn, false, false, 0); window_box.pack_start (hist_box, false, false, 0);

        notebook.append_page (window_scroll, new Gtk.Label (_("Window")));

        this.add_button (_("Close"), Gtk.ResponseType.CLOSE);
        this.show_all ();
    }
}

public class DesignThemedBox : Gtk.EventBox {
    public TechHudStarterWindow parent_win;
    private Gtk.Widget child_widget;
    private bool is_entry = false;
    private bool is_output = false;
    private bool cursor_visible = true;
    private uint blink_id = 0;

    public DesignThemedBox (Gtk.Widget child, TechHudStarterWindow win) {
        parent_win = win;
        child_widget = child;
        this.set_visible_window (false);
        this.set_app_paintable (true);
        this.set_above_child (false);

        is_entry = (child is Gtk.Entry);
        is_output = (child is Gtk.ScrolledWindow);

        child_widget.set_opacity (0.0);

        if (child_widget is Gtk.Entry) {
            var e = child_widget as Gtk.Entry;
            e.set_has_frame (false);
            e.focus_in_event.connect (() => { start_blink (); return false; });
            e.focus_out_event.connect (() => { stop_blink (); return false; });
            e.changed.connect (() => { this.queue_draw (); });
        }

        this.add (child);
        this.draw.connect (on_draw_themed_box);
    }

    private void start_blink () {
        if (blink_id != 0) return;
        cursor_visible = true;
        blink_id = Timeout.add (530, () => {
            cursor_visible = !cursor_visible;
            queue_draw ();
            return true;
        });
    }

    private void stop_blink () {
        if (blink_id != 0) {
            Source.remove (blink_id);
            blink_id = 0;
        }
        cursor_visible = false;
        queue_draw ();
    }

    private bool on_draw_themed_box (Widget widget, Context cr) {
        var t = ThemeManager.get_theme (parent_win.theme_index);
        double w = get_allocated_width ();
        double h = get_allocated_height ();

        int cat = parent_win.element_design_category;
        int fixed_cat = (cat == 1) ? 2 : ((cat == 2) ? 1 : 0);
        double eff_bg = parent_win.element_bg_opacity;
        if (eff_bg > 0.99) eff_bg = 1.0;

        if (eff_bg >= 1.0) {
            cr.save ();
            cr.set_source_rgba (0.98, 0.98, 0.98, 1.0);
            HudDesignSystem.build_path_for_style (cr, 1, 1, w - 2, h - 2, parent_win.border_style, parent_win.ui_scale);
            cr.fill ();
            cr.restore ();
        }

        HudDesignSystem.apply_panel_fill (cr, w, h, t, fixed_cat, parent_win.element_glass_variant, eff_bg);
        HudDesignSystem.build_path_for_style (cr, 1, 1, w - 2, h - 2, parent_win.border_style, parent_win.ui_scale);
        cr.fill ();

        double br = parent_win.use_custom_border ? parent_win.custom_border_r : t.border_r;
        double bg = parent_win.use_custom_border ? parent_win.custom_border_g : t.border_g;
        double bb = parent_win.use_custom_border ? parent_win.custom_border_b : t.border_b;

        cr.set_source_rgba (br, bg, bb, parent_win.element_border_opacity);
        cr.set_line_width (1.2 * parent_win.ui_scale);
        HudDesignSystem.build_path_for_style (cr, 1, 1, w - 2, h - 2, parent_win.border_style, parent_win.ui_scale);
        cr.stroke ();

        double tr = parent_win.use_border_for_primary ? br : parent_win.custom_primary_r;
        double tg = parent_win.use_border_for_primary ? bg : parent_win.custom_primary_g;
        double tb = parent_win.use_border_for_primary ? bb : parent_win.custom_primary_b;
        double font_size = 11 * parent_win.text_scale;
        double pad = 8 * parent_win.ui_scale;

        if (is_entry && child_widget is Gtk.Entry) {
            var e = child_widget as Gtk.Entry;
            string txt = e.get_text ();
            if (txt == "") {
                txt = e.get_placeholder_text ();
                if (txt != null && txt != "") {
                    cr.set_source_rgba (tr, tg, tb, 0.5);
                    cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.NORMAL);
                    cr.set_font_size (font_size);
                    cr.move_to (pad, h/2 + font_size/3);
                    cr.show_text (txt);
                }
            } else {
                HudDesignSystem.draw_text_with_effects (cr, txt, pad, h/2 + font_size/3, font_size, tr, tg, tb, parent_win.text_opacity, parent_win.text_3d_style, parent_win.use_text_shadow, parent_win.text_shadow_style);
            }
            if (e.has_focus && cursor_visible) {
                Cairo.TextExtents ext;
                cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.NORMAL);
                cr.set_font_size (font_size);
                cr.text_extents (e.get_text (), out ext);
                double cx = pad + ext.width + 2;
                if (e.get_text () == "") cx = pad + 2;
                cr.set_source_rgba (tr, tg, tb, 0.95);
                cr.set_line_width (1.4);
                double ch = font_size * 1.1;
                double cy = h/2 - ch/2;
                cr.move_to (cx, cy);
                cr.line_to (cx, cy + ch);
                cr.stroke ();
            }
        } else if (is_output && child_widget is Gtk.ScrolledWindow) {
            var sw = child_widget as Gtk.ScrolledWindow;
            var tv = sw.get_child () as Gtk.TextView;
            if (tv != null) {
                var buf = tv.get_buffer ();
                Gtk.TextIter start, end;
                buf.get_start_iter (out start);
                buf.get_end_iter (out end);
                string all = buf.get_text (start, end, false);
                string[] lines = all.split ("
");
                double y = pad + font_size;
                foreach (var line in lines) {
                    if (y > h - pad) break;
                    if (line.strip () != "") {
                        HudDesignSystem.draw_text_with_effects (cr, line, pad, y, font_size * 0.95, tr, tg, tb, parent_win.text_opacity, parent_win.text_3d_style, parent_win.use_text_shadow, parent_win.text_shadow_style);
                    }
                    y += font_size + 4 * parent_win.ui_scale;
                }
            }
        }

        return false;
    }
}

public class PaintedButton : Gtk.EventBox {
    private string label_text;
    public signal void clicked ();
    public TechHudStarterWindow parent_win;
    private bool is_hovered = false;

    public PaintedButton (string text, TechHudStarterWindow win) {
        label_text = text;
        parent_win = win;
        this.set_visible_window (false);
        this.set_events (Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK);
        update_scaling ();
        this.button_press_event.connect ((e) => {
            if (e.type == Gdk.EventType.DOUBLE_BUTTON_PRESS || e.type == Gdk.EventType.TRIPLE_BUTTON_PRESS) return true;
            if (e.button == 1) { clicked (); return true; }
            return false;
        });
        this.enter_notify_event.connect (() => { is_hovered = true; queue_draw (); return false; });
        this.leave_notify_event.connect (() => { is_hovered = false; queue_draw (); return false; });
        this.draw.connect (on_draw_button);
    }

    public void update_scaling () {
        var surf = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1);
        var cr = new Cairo.Context (surf);
        cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.BOLD);
        cr.set_font_size (11 * parent_win.text_scale);
        Cairo.TextExtents ext;
        cr.text_extents (label_text, out ext);
        int needed_w = (int)(ext.width + 48 * parent_win.ui_scale + 24 * parent_win.text_scale);
        int base_w = (int)(110 * parent_win.ui_scale);
        if (needed_w < base_w) needed_w = base_w;
        int needed_h = (int)(ext.height + 18 * parent_win.ui_scale);
        int base_h = (int)(28 * parent_win.ui_scale);
        if (needed_h < base_h) needed_h = base_h;
        if (needed_h > (int)(38 * parent_win.ui_scale)) needed_h = (int)(38 * parent_win.ui_scale);
        this.set_size_request (needed_w, needed_h);
        queue_draw ();
    }

    private bool on_draw_button (Widget widget, Context cr) {
        var t = ThemeManager.get_theme (parent_win.theme_index);
        double w = get_allocated_width (); double h = get_allocated_height ();
        double bx = 2 * parent_win.ui_scale; double by = 2 * parent_win.ui_scale;
        double bw = w - (4 * parent_win.ui_scale); double bh = h - (4 * parent_win.ui_scale);
        int cat = parent_win.element_design_category;
        int fixed_cat = (cat == 1) ? 2 : ((cat == 2) ? 1 : 0);
        double eff_bg = parent_win.element_bg_opacity;
        if (eff_bg > 0.99) eff_bg = 1.0;
        if (eff_bg >= 1.0) {
            cr.save ();
            cr.set_source_rgba (0.98, 0.98, 0.98, 1.0);
            HudDesignSystem.build_path_for_style (cr, bx, by, bw, bh, parent_win.border_style, parent_win.ui_scale);
            cr.fill ();
            cr.restore ();
        }
        HudDesignSystem.apply_panel_fill (cr, bw, bh, t, fixed_cat, parent_win.element_glass_variant, eff_bg);
        HudDesignSystem.build_path_for_style (cr, bx, by, bw, bh, parent_win.border_style, parent_win.ui_scale);
        cr.fill_preserve ();
        if (is_hovered) {
            cr.set_source_rgba (t.accent_r, t.accent_g, t.accent_b, 0.18);
            cr.fill_preserve ();
            cr.set_source_rgba (1, 1, 1, 0.06);
            cr.fill_preserve ();
        }
        double br = parent_win.use_custom_border ? parent_win.custom_border_r : t.border_r;
        double bg = parent_win.use_custom_border ? parent_win.custom_border_g : t.border_g;
        double bb = parent_win.use_custom_border ? parent_win.custom_border_b : t.border_b;
        cr.set_source_rgba (br, bg, bb, parent_win.element_border_opacity);
        cr.set_line_width (1.2 * parent_win.ui_scale);
        cr.stroke ();
        double font_size = 11 * parent_win.text_scale;
        Cairo.TextExtents extents;
        cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.BOLD);
        cr.set_font_size (font_size);
        cr.text_extents (label_text, out extents);
        double text_x = (w - extents.width) / 2 - extents.x_bearing;
        double text_y = (h - extents.height) / 2 - extents.y_bearing;
        double tr = parent_win.use_border_for_primary ? br : parent_win.custom_primary_r;
        double tg = parent_win.use_border_for_primary ? bg : parent_win.custom_primary_g;
        double tb = parent_win.use_border_for_primary ? bb : parent_win.custom_primary_b;
        HudDesignSystem.draw_text_with_effects (cr, label_text, text_x, text_y, font_size, tr, tg, tb, parent_win.text_opacity, parent_win.text_3d_style, parent_win.use_text_shadow, parent_win.text_shadow_style);
        return false;
    }
}

public class PaintedCheckButton : Gtk.EventBox {
    public bool active { get; set; default = false; }
    private string label_text;
    public signal void toggled ();
    public TechHudStarterWindow parent_win;
    private bool is_hovered = false;

    public PaintedCheckButton (string text, TechHudStarterWindow win) {
        label_text = text;
        parent_win = win;
        this.set_visible_window (false);
        this.set_events (Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK);
        update_scaling ();
        this.button_press_event.connect ((e) => {
            if (e.type == Gdk.EventType.DOUBLE_BUTTON_PRESS || e.type == Gdk.EventType.TRIPLE_BUTTON_PRESS) return true;
            if (e.button == 1) { active = !active; toggled (); queue_draw (); return true; }
            return false;
        });
        this.enter_notify_event.connect (() => { is_hovered = true; queue_draw (); return false; });
        this.leave_notify_event.connect (() => { is_hovered = false; queue_draw (); return false; });
        this.draw.connect (on_draw_check);
    }

    public void update_scaling () {
        var surf = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1);
        var cr = new Cairo.Context (surf);
        cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.BOLD);
        cr.set_font_size (11 * parent_win.text_scale);
        Cairo.TextExtents ext;
        cr.text_extents (label_text, out ext);
        int needed_w = (int)(ext.width + 36 * parent_win.ui_scale + 12 * parent_win.text_scale);
        int base_w = (int)(110 * parent_win.ui_scale);
        if (needed_w < base_w) needed_w = base_w;
        int needed_h = (int)(ext.height + 14 * parent_win.ui_scale);
        int base_h = (int)(26 * parent_win.ui_scale);
        if (needed_h < base_h) needed_h = base_h;
        if (needed_h > (int)(36 * parent_win.ui_scale)) needed_h = (int)(36 * parent_win.ui_scale);
        this.set_size_request (needed_w, needed_h);
        queue_draw ();
    }

    private bool on_draw_check (Widget widget, Context cr) {
        var t = ThemeManager.get_theme (parent_win.theme_index);
        double h = get_allocated_height ();
        double box_size = 22.0 * parent_win.ui_scale;
        double box_y = (h - box_size) / 2.0;
        double box_x = 4.0 * parent_win.ui_scale;
        int cat = parent_win.element_design_category;
        int fixed_cat = (cat == 1) ? 2 : ((cat == 2) ? 1 : 0);
        double eff_bg = parent_win.element_bg_opacity;
        if (eff_bg > 0.99) eff_bg = 1.0;
        if (eff_bg >= 1.0) {
            cr.save ();
            cr.set_source_rgba (0.98, 0.98, 0.98, 1.0);
            HudDesignSystem.build_path_for_style (cr, box_x, box_y, box_size, box_size, parent_win.border_style, parent_win.ui_scale);
            cr.fill ();
            cr.restore ();
        }
        HudDesignSystem.apply_panel_fill (cr, box_size, box_size, t, fixed_cat, parent_win.element_glass_variant, eff_bg);
        HudDesignSystem.build_path_for_style (cr, box_x, box_y, box_size, box_size, parent_win.border_style, parent_win.ui_scale);
        cr.fill_preserve ();
        double br = parent_win.use_custom_border ? parent_win.custom_border_r : t.border_r;
        double bg = parent_win.use_custom_border ? parent_win.custom_border_g : t.border_g;
        double bb = parent_win.use_custom_border ? parent_win.custom_border_b : t.border_b;
        cr.set_source_rgba (br, bg, bb, parent_win.element_border_opacity);
        cr.set_line_width (1.2 * parent_win.ui_scale);
        cr.stroke ();
        if (is_hovered) {
            cr.set_source_rgba (t.accent_r, t.accent_g, t.accent_b, 0.2);
            HudDesignSystem.build_path_for_style (cr, box_x, box_y, box_size, box_size, parent_win.border_style, parent_win.ui_scale);
            cr.fill ();
        }
        if (active) {
            cr.set_source_rgba (br, bg, bb, parent_win.element_border_opacity);
            cr.set_line_width (2.0 * parent_win.ui_scale);
            cr.move_to (box_x + (4.0 * parent_win.ui_scale), box_y + box_size / 2.0);
            cr.line_to (box_x + box_size / 2.0 - (1.0 * parent_win.ui_scale), box_y + box_size - (4.0 * parent_win.ui_scale));
            cr.line_to (box_x + box_size - (3.0 * parent_win.ui_scale), box_y + (4.0 * parent_win.ui_scale));
            cr.stroke ();
        }
        double font_size = 11 * parent_win.text_scale;
        Cairo.TextExtents extents;
        cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.BOLD);
        cr.set_font_size (font_size);
        cr.text_extents (label_text, out extents);
        double text_x = box_x + box_size + (8.0 * parent_win.ui_scale);
        double text_y = (h - extents.height) / 2 - extents.y_bearing;
        double tr = parent_win.use_border_for_primary ? br : parent_win.custom_primary_r;
        double tg = parent_win.use_border_for_primary ? bg : parent_win.custom_primary_g;
        double tb = parent_win.use_border_for_primary ? bb : parent_win.custom_primary_b;
        HudDesignSystem.draw_text_with_effects (cr, label_text, text_x, text_y, font_size, tr, tg, tb, parent_win.text_opacity, parent_win.text_3d_style, parent_win.use_text_shadow, parent_win.text_shadow_style);
        return false;
    }
}

public class PaintedSpinButton : Gtk.EventBox {
    public double value { get; set; default = 10.0; }
    public double min_val { get; set; default = 1.0; }
    public double max_val { get; set; default = 3600.0; }
    public double step { get; set; default = 1.0; }
    public signal void value_changed ();
    public TechHudStarterWindow parent_win;
    private int hovered_part = 0;

    public PaintedSpinButton (double initial_value, double min, double max, double stp, TechHudStarterWindow win) {
        this.value = initial_value;
        this.min_val = min;
        this.max_val = max;
        this.step = stp;
        parent_win = win;
        this.set_visible_window (false);
        this.set_events (Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK);
        update_scaling ();
        this.button_press_event.connect ((e) => {
            if (e.type == Gdk.EventType.DOUBLE_BUTTON_PRESS || e.type == Gdk.EventType.TRIPLE_BUTTON_PRESS) return true;
            if (e.button == 1) {
                double w = get_allocated_width (); double btn_w = 30 * parent_win.ui_scale;
                if (e.x < btn_w) { value -= step; if (value < min_val) value = min_val; value_changed (); queue_draw (); }
                else if (e.x > w - btn_w) { value += step; if (value > max_val) value = max_val; value_changed (); queue_draw (); }
                return true;
            }
            return false;
        });
        this.scroll_event.connect ((e) => {
            if (e.direction == Gdk.ScrollDirection.UP) { value += step; if (value > max_val) value = max_val; }
            else if (e.direction == Gdk.ScrollDirection.DOWN) { value -= step; if (value < min_val) value = min_val; }
            value_changed (); queue_draw (); return true;
        });
        this.motion_notify_event.connect ((e) => {
            double w = get_allocated_width (); double btn_w = 30 * parent_win.ui_scale;
            int old_part = hovered_part;
            if (e.x < btn_w) hovered_part = 1; else if (e.x > w - btn_w) hovered_part = 3; else hovered_part = 2;
            if (old_part != hovered_part) queue_draw ();
            return false;
        });
        this.leave_notify_event.connect (() => { hovered_part = 0; queue_draw (); return false; });
        this.draw.connect (on_draw_spin);
    }

    public void update_scaling () {
        var surf = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1);
        var cr = new Cairo.Context (surf);
        cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.BOLD);
        cr.set_font_size (11 * parent_win.text_scale);
        Cairo.TextExtents ext;
        cr.text_extents ("10", out ext);
        int needed_w = (int)(ext.width + 70 * parent_win.ui_scale + 20 * parent_win.text_scale);
        if (needed_w < (int)(110 * parent_win.ui_scale)) needed_w = (int)(110 * parent_win.ui_scale);
        int needed_h = (int)(ext.height + 16 * parent_win.ui_scale);
        int base_h = (int)(28 * parent_win.ui_scale);
        if (needed_h < base_h) needed_h = base_h;
        if (needed_h > (int)(38 * parent_win.ui_scale)) needed_h = (int)(38 * parent_win.ui_scale);
        this.set_size_request (needed_w, needed_h);
        queue_draw ();
    }

    private bool on_draw_spin (Widget widget, Context cr) {
        var t = ThemeManager.get_theme (parent_win.theme_index);
        double w = get_allocated_width (); double h = get_allocated_height ();
        double btn_w = 30 * parent_win.ui_scale;
        int cat = parent_win.element_design_category;
        int fixed_cat = (cat == 1) ? 2 : ((cat == 2) ? 1 : 0);
        double eff_bg = parent_win.element_bg_opacity;
        if (eff_bg > 0.99) eff_bg = 1.0;
        if (eff_bg >= 1.0) {
            cr.save ();
            cr.set_source_rgba (0.98, 0.98, 0.98, 1.0);
            HudDesignSystem.build_path_for_style (cr, 2 * parent_win.ui_scale, 2 * parent_win.ui_scale, w - (4 * parent_win.ui_scale), h - (4 * parent_win.ui_scale), parent_win.border_style, parent_win.ui_scale);
            cr.fill ();
            cr.restore ();
        }
        HudDesignSystem.apply_panel_fill (cr, w - (4 * parent_win.ui_scale), h - (4 * parent_win.ui_scale), t, fixed_cat, parent_win.element_glass_variant, eff_bg);
        HudDesignSystem.build_path_for_style (cr, 2 * parent_win.ui_scale, 2 * parent_win.ui_scale, w - (4 * parent_win.ui_scale), h - (4 * parent_win.ui_scale), parent_win.border_style, parent_win.ui_scale);
        cr.fill_preserve ();
        double br = parent_win.use_custom_border ? parent_win.custom_border_r : t.border_r;
        double bg = parent_win.use_custom_border ? parent_win.custom_border_g : t.border_g;
        double bb = parent_win.use_custom_border ? parent_win.custom_border_b : t.border_b;
        cr.set_source_rgba (br, bg, bb, parent_win.element_border_opacity);
        cr.set_line_width (1.2 * parent_win.ui_scale);
        cr.stroke ();
        cr.set_source_rgba (br, bg, bb, 0.4);
        cr.set_line_width (1.0 * parent_win.ui_scale);
        cr.move_to (btn_w, 4 * parent_win.ui_scale); cr.line_to (btn_w, h - (4 * parent_win.ui_scale)); cr.stroke ();
        cr.move_to (w - btn_w, 4 * parent_win.ui_scale); cr.line_to (w - btn_w, h - (4 * parent_win.ui_scale)); cr.stroke ();
        if (hovered_part == 1) {
            cr.set_source_rgba (t.accent_r, t.accent_g, t.accent_b, 0.15);
            HudDesignSystem.build_path_for_style (cr, 2 * parent_win.ui_scale, 2 * parent_win.ui_scale, btn_w - (2 * parent_win.ui_scale), h - (4 * parent_win.ui_scale), parent_win.border_style, parent_win.ui_scale);
            cr.fill ();
        } else if (hovered_part == 3) {
            cr.set_source_rgba (t.accent_r, t.accent_g, t.accent_b, 0.15);
            HudDesignSystem.build_path_for_style (cr, w - btn_w, 2 * parent_win.ui_scale, btn_w - (2 * parent_win.ui_scale), h - (4 * parent_win.ui_scale), parent_win.border_style, parent_win.ui_scale);
            cr.fill ();
        }
        double font_size = 11 * parent_win.text_scale;
        Cairo.TextExtents extents;
        cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.BOLD);
        cr.set_font_size (font_size);
        double tr = parent_win.use_border_for_primary ? br : parent_win.custom_primary_r;
        double tg = parent_win.use_border_for_primary ? bg : parent_win.custom_primary_g;
        double tb = parent_win.use_border_for_primary ? bb : parent_win.custom_primary_b;
        cr.text_extents ("-", out extents);
        double minus_x = (btn_w / 2) - extents.width / 2 - extents.x_bearing;
        double minus_y = (h - extents.height) / 2 - extents.y_bearing;
        HudDesignSystem.draw_text_with_effects (cr, "-", minus_x, minus_y, font_size, tr, tg, tb, parent_win.text_opacity, parent_win.text_3d_style, parent_win.use_text_shadow, parent_win.text_shadow_style);
        cr.text_extents ("+", out extents);
        double plus_x = (w - btn_w / 2) - extents.width / 2 - extents.x_bearing;
        double plus_y = (h - extents.height) / 2 - extents.y_bearing;
        HudDesignSystem.draw_text_with_effects (cr, "+", plus_x, plus_y, font_size, tr, tg, tb, parent_win.text_opacity, parent_win.text_3d_style, parent_win.use_text_shadow, parent_win.text_shadow_style);
        string val_str = ((int)value).to_string ();
        cr.text_extents (val_str, out extents);
        double val_x = btn_w + (w - (2 * btn_w) - extents.width) / 2 - extents.x_bearing;
        double val_y = (h - extents.height) / 2 - extents.y_bearing;
        HudDesignSystem.draw_text_with_effects (cr, val_str, val_x, val_y, font_size, tr, tg, tb, parent_win.text_opacity, parent_win.text_3d_style, parent_win.use_text_shadow, parent_win.text_shadow_style);
        return false;
    }
}

public class TechHudStarterWindow : Gtk.Window {
    private string config_path;
    private string history_path;
    public int theme_index = 2;
    public int border_style = 1;
    public int design_category = 0;
    public int glass_variant = 0;
    public int element_design_category = 0;
    public int element_glass_variant = 0;
    public double ui_scale = 1.0;
    public double text_scale = 1.0;
    public double window_opacity = 1.0;
    public double bg_opacity = 0.95;
    public double text_opacity = 1.0;
    public double border_opacity = 0.85;
    public double element_bg_opacity = 0.95;
    public double element_border_opacity = 0.85;
    public int text_3d_style = 0;
    public bool use_text_shadow = false;
    public int text_shadow_style = 0;
    public bool use_custom_border = false;
    public double custom_border_r = 0.8;
    public double custom_border_g = 0.5;
    public double custom_border_b = 0.3;
    public bool use_border_for_primary = true;
    public double custom_primary_r = 0.9;
    public double custom_primary_g = 1.0;
    public double custom_primary_b = 1.0;

    public int window_width = 680;
    public int window_height = 520;
    public int window_type_hint_mode = 0;
    public string window_layer = "normal";
    public bool window_sticky = false;
    public bool has_saved_position = false;
    public int saved_pos_x = 100;
    public int saved_pos_y = 100;

    private Gtk.Entry command_entry;
    private Gtk.TextView output_view;
    private Gtk.TextBuffer output_buffer;
    private Gtk.CssProvider css_provider;

    private Gtk.Box header_box;
    private Gtk.Box main_vbox;
    private DesignThemedBox entry_themed_box;
    private DesignThemedBox scrolled_themed_box;

    private PaintedCheckButton repeat_check;
    private PaintedSpinButton repeat_spin;
    private Gtk.Label countdown_label;
    private uint repeat_timer_id = 0;
    private uint countdown_timer_id = 0;
    private int remaining_seconds = 10;
    private string last_executed_cmd = "";

    private string[] history = {};
    private int history_index = -1;
    private string current_input_backup = "";

    public TechHudStarterWindow () {
        this.title = _("Tech HUD Command Center");
        this.set_app_paintable (true);
        this.decorated = false;

        string config_dir = GLib.Path.build_filename (Environment.get_user_config_dir (), "tech_hud");
        DirUtils.create_with_parents (config_dir, 0755);
        config_path = GLib.Path.build_filename (config_dir, "config.conf");
        history_path = GLib.Path.build_filename (config_dir, "history.txt");

        load_config ();
        load_history ();

        if (has_saved_position) {
            this.move (saved_pos_x, saved_pos_y);
        } else {
            this.set_position (WindowPosition.CENTER);
        }

        apply_window_settings ();

        var screen = this.get_screen ();
        var visual = screen.get_rgba_visual ();
        if (visual != null) {
            this.set_visual (visual);
        }

        css_provider = new Gtk.CssProvider ();
        update_theme_styling ();

        this.add_events (Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.KEY_PRESS_MASK);

        main_vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, (int)(10 * ui_scale));
        main_vbox.margin = (int)(28 * ui_scale);

        header_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, (int)(6 * ui_scale));
        header_box.set_valign (Gtk.Align.START);

        var repeat_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, (int)(4 * ui_scale));
        repeat_check = new PaintedCheckButton (_("Repeat every"), this);
        repeat_check.toggled.connect (on_repeat_toggled);
        repeat_box.pack_start (repeat_check, false, false, 0);

        repeat_spin = new PaintedSpinButton (10.0, 1.0, 3600.0, 1.0, this);
        repeat_spin.value_changed.connect (() => {
            if (repeat_check.active) {
                setup_repeat_timer ();
            }
        });
        repeat_box.pack_start (repeat_spin, false, false, 0);

        var seconds_label = new Gtk.Label ("s");
        repeat_box.pack_start (seconds_label, false, false, 0);

        countdown_label = new Gtk.Label ("");
        countdown_label.set_visible (false);
        repeat_box.pack_start (countdown_label, false, false, 0);

        header_box.pack_start (repeat_box, false, false, 0);

        var spacer = new Gtk.Label ("");
        spacer.set_hexpand (true);
        header_box.pack_start (spacer, true, true, 0);

        var options_btn = new PaintedButton (_("Optionen..."), this);
        options_btn.clicked.connect (() => {
            var dlg = new TechHudStarterOptionsDialog (this);
            dlg.run ();
            dlg.destroy ();
        });
        header_box.pack_end (options_btn, false, false, 0);

        main_vbox.pack_start (header_box, false, false, 0);

        command_entry = new Gtk.Entry ();
        command_entry.set_has_frame (false);
        command_entry.set_placeholder_text (_("Type a command or shell action and press Enter..."));
        command_entry.activate.connect (on_command_activate);
        command_entry.key_press_event.connect (on_entry_key_press);

        entry_themed_box = new DesignThemedBox (command_entry, this);
        entry_themed_box.set_size_request (-1, (int)(11 * text_scale + 20 * ui_scale));
        main_vbox.pack_start (entry_themed_box, false, false, 0);

        output_view = new Gtk.TextView ();
        output_view.set_editable (false);
        output_view.set_monospace (true);
        output_buffer = output_view.get_buffer ();

        var scrolled = new Gtk.ScrolledWindow (null, null);
        scrolled.set_shadow_type (Gtk.ShadowType.NONE);
        scrolled.add (output_view);

        scrolled_themed_box = new DesignThemedBox (scrolled, this);
        scrolled_themed_box.set_size_request (-1, (int)(180 * ui_scale));
        scrolled_themed_box.set_vexpand (true);
        main_vbox.pack_start (scrolled_themed_box, true, true, 0);

        main_vbox.set_hexpand (true);
        this.add (main_vbox);

        this.draw.connect (on_draw);
        this.button_press_event.connect (on_button_press);
        this.key_press_event.connect (on_key_press);

        this.configure_event.connect ((e) => {
            int rx, ry;
            this.get_position (out rx, out ry);
            saved_pos_x = rx;
            saved_pos_y = ry;
            has_saved_position = true;

            int rw, rh;
            this.get_size (out rw, out rh);
            window_width = rw;
            window_height = rh;
            save_config ();
            return false;
        });

        this.show_all ();
        append_output (_("Tech HUD Starter initialized successfully."));
    }

    public string[] get_history_array () {
        return history;
    }

    public void set_history_from_text (string text) {
        string[] lines = text.split ("\n");
        string[] new_history = {};
        foreach (var line in lines) {
            string trimmed = line.strip ();
            if (trimmed != "") {
                string[] filtered = {};
                foreach (var h in new_history) {
                    if (h != trimmed) filtered += h;
                }
                filtered += trimmed;
                new_history = filtered;
            }
        }
        history = new_history;
        save_history ();
        history_index = -1;
        current_input_backup = "";
    }

    public void apply_and_save () {
        apply_window_settings ();
        update_theme_styling ();

        if (repeat_check != null) repeat_check.update_scaling ();
        if (repeat_spin != null) repeat_spin.update_scaling ();
        if (main_vbox != null) {
            main_vbox.margin = (int)(28 * ui_scale);
            main_vbox.spacing = (int)(10 * ui_scale);
        }

        save_config ();
        this.queue_draw ();
        if (entry_themed_box != null) entry_themed_box.queue_draw ();
        if (scrolled_themed_box != null) scrolled_themed_box.queue_draw ();
    }

    public void apply_window_settings () {
        this.resize (window_width, window_height);
        this.opacity = 1.0;

        switch (window_type_hint_mode) {
            case 1: this.set_type_hint (Gdk.WindowTypeHint.UTILITY); break;
            case 2: this.set_type_hint (Gdk.WindowTypeHint.DOCK); break;
            default: this.set_type_hint (Gdk.WindowTypeHint.NORMAL); break;
        }

        if (window_layer == "above") {
            this.set_keep_below (false);
            this.set_keep_above (true);
        } else if (window_layer == "below") {
            this.set_keep_above (false);
            this.set_keep_below (true);
        } else {
            this.set_keep_above (false);
            this.set_keep_below (false);
        }

        if (window_sticky) {
            this.stick ();
        } else {
            this.unstick ();
        }

        if (this.get_realized ()) {
            var gdk_win = this.get_window ();
            if (gdk_win != null) {
                gdk_win.set_override_redirect (false);
            }
        }
    }

    private void update_theme_styling () {
        var t = ThemeManager.get_theme (theme_index);
        int font_sz = (int)(11 * ui_scale);
        double br = use_custom_border ? custom_border_r : t.border_r;
        double bg = use_custom_border ? custom_border_g : t.border_g;
        double bb = use_custom_border ? custom_border_b : t.border_b;
        double tr = use_border_for_primary ? br : custom_primary_r;
        double tg = use_border_for_primary ? bg : custom_primary_g;
        double tb = use_border_for_primary ? bb : custom_primary_b;

        string css = ("entry, entry text, textview, textview text, scrolledwindow, viewport, frame { " +
            "background-color: transparent; " +
            "background-image: none; " +
            "box-shadow: none; " +
            "border: none; " +
            "color: rgba(%d, %d, %d, %.2f); " +
            "font-size: %dpt; " +
            "} " +
            "entry selection, textview text selection { " +
            "background-color: rgba(%d, %d, %d, 0.4); " +
            "} " +
            "label { " +
            "color: rgba(%d, %d, %d, %.2f); " +
            "font-size: %dpt; " +
            "}").printf (
            (int)(tr * 255), (int)(tg * 255), (int)(tb * 255), text_opacity,
            font_sz,
            (int)(br * 255), (int)(bg * 255), (int)(bb * 255),
            (int)(tr * 255), (int)(tg * 255), (int)(tb * 255), text_opacity,
            font_sz
        );

        try {
            css_provider.load_from_data (css);
            Gtk.StyleContext.add_provider_for_screen (this.get_screen (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
        } catch (Error e) {}
    }

    private bool on_draw (Widget widget, Context cr) {
        var t = ThemeManager.get_theme (theme_index);

        cr.save ();
        cr.scale (ui_scale, ui_scale);

        double unscaled_w = get_allocated_width () / ui_scale;
        double unscaled_h = get_allocated_height () / ui_scale;

        cr.set_source_rgba (0, 0, 0, 0);
        cr.set_operator (Cairo.Operator.SOURCE);
        cr.paint ();
        cr.set_operator (Cairo.Operator.OVER);

        double hud_x = 12;
        double hud_y = 12;
        double hud_w = unscaled_w - 24;
        double hud_h = unscaled_h - 24;

        double eff_bg_main = bg_opacity;
        if (eff_bg_main > 0.99) eff_bg_main = 1.0;

        if (eff_bg_main >= 1.0) {
            cr.save ();
            cr.set_source_rgba (0.98, 0.98, 0.98, 1.0);
            HudDesignSystem.build_path_for_style (cr, hud_x, hud_y, hud_w, hud_h, border_style, 1.0);
            cr.fill ();
            cr.restore ();
        }

        HudDesignSystem.build_path_for_style (cr, hud_x, hud_y, hud_w, hud_h, border_style, 1.0);
        HudDesignSystem.apply_panel_fill (cr, hud_w, hud_h, t, design_category, glass_variant, eff_bg_main);

        double br = use_custom_border ? custom_border_r : t.border_r;
        double bg = use_custom_border ? custom_border_g : t.border_g;
        double bb = use_custom_border ? custom_border_b : t.border_b;

        cr.set_source_rgba (br, bg, bb, border_opacity);
        cr.set_line_width (1.5);
        HudDesignSystem.build_path_for_style (cr, hud_x, hud_y, hud_w, hud_h, border_style, 1.0);
        cr.stroke ();

        cr.set_source_rgba (br, bg, bb, border_opacity * 0.3);
        cr.set_line_width (0.75);
        HudDesignSystem.build_path_for_style (cr, hud_x + 6, hud_y + 6, hud_w - 12, hud_h - 12, border_style, 1.0);
        cr.stroke ();

        cr.restore ();
        return false;
    }

    private bool on_button_press (Gdk.EventButton event) {
        if (event.button == 3) {
            var menu = new Gtk.Menu ();
            var options_item = new Gtk.MenuItem.with_label (_("Options..."));
            options_item.activate.connect (() => {
                var dlg = new TechHudStarterOptionsDialog (this);
                dlg.run ();
                dlg.destroy ();
            });
            var close_item = new Gtk.MenuItem.with_label (_("Close"));
            close_item.activate.connect (() => {
                stop_repeat_timer ();
                Gtk.main_quit ();
            });
            menu.append (options_item);
            menu.append (new Gtk.SeparatorMenuItem ());
            menu.append (close_item);
            menu.show_all ();
            menu.popup_at_pointer (event);
            return true;
        }

        if (event.type == Gdk.EventType.DOUBLE_BUTTON_PRESS || event.type == Gdk.EventType.TRIPLE_BUTTON_PRESS) {
            return true;
        }
        if (event.button == 1) {
            int win_w, win_h;
            this.get_size (out win_w, out win_h);

            if (event.x >= win_w - 20 && event.y >= win_h - 20) {
                this.begin_resize_drag (Gdk.WindowEdge.SOUTH_EAST, (int)event.button, (int)event.x_root, (int)event.y_root, event.time);
                return true;
            }

            int wx, wy;
            header_box.translate_coordinates (this, 0, 0, out wx, out wy);
            if (event.x >= wx && event.x <= wx + header_box.get_allocated_width () &&
                event.y >= wy && event.y <= wy + header_box.get_allocated_height ()) {
                this.begin_move_drag ((int)event.button, (int)event.x_root, (int)event.y_root, event.time);
                return true;
            }
        }
        return false;
    }

    private bool on_entry_key_press (Gdk.EventKey event) {
        if (history.length == 0) return false;

        if (event.keyval == Gdk.Key.Up) {
            if (history_index == -1) {
                current_input_backup = command_entry.get_text ();
                history_index = history.length - 1;
            } else if (history_index > 0) {
                history_index--;
            }
            command_entry.set_text (history[history_index]);
            command_entry.set_position (-1);
            return true;
        } else if (event.keyval == Gdk.Key.Down) {
            if (history_index != -1) {
                history_index++;
                if (history_index < history.length) {
                    command_entry.set_text (history[history_index]);
                } else {
                    history_index = -1;
                    command_entry.set_text (current_input_backup);
                }
                command_entry.set_position (-1);
            }
            return true;
        }
        return false;
    }

    private void on_command_activate () {
        string cmd = command_entry.get_text ().strip ();
        if (cmd == "") return;

        if (cmd.down () == "exit" || cmd.down () == "quit") {
            stop_repeat_timer ();
            Gtk.main_quit ();
            return;
        }

        string[] new_history = {};
        foreach (var h in history) {
            if (h != cmd) {
                new_history += h;
            }
        }
        new_history += cmd;
        history = new_history;
        save_history ();

        history_index = -1;
        current_input_backup = "";
        command_entry.set_text ("");

        last_executed_cmd = cmd;
        execute_command_once (cmd);
        setup_repeat_timer ();
    }

    private void execute_command_once (string cmd) {
        append_output ("> " + cmd);

        bool run_in_background = false;
        string clean_cmd = cmd;

        if (clean_cmd.has_suffix ("&") && !clean_cmd.has_suffix ("&&")) {
            run_in_background = true;
            clean_cmd = clean_cmd.substring (0, clean_cmd.length - 1).strip ();
        }

        string[] parts = clean_cmd.split (";");
        bool has_clear = false;
        string[] run_parts = {};

        foreach (var part in parts) {
            string p = part.strip ();
            if (p.down () == "clear") {
                has_clear = true;
            } else if (p != "") {
                run_parts += p;
            }
        }

        if (has_clear) {
            output_buffer.set_text ("");
        }

        if (run_parts.length > 0) {
            string exec_cmd = string.joinv (";", run_parts);
            try {
                if (run_in_background) {
                    string[] spawned_argv = { "sh", "-c", exec_cmd };
                    GLib.Process.spawn_async (null, spawned_argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null);
                    append_output (_("[Launched in background]"));
                } else {
                    string standard_output;
                    string standard_error;
                    int exit_status;

                    string[] spawned_argv = { "sh", "-c", exec_cmd };
                    GLib.Process.spawn_sync (null, spawned_argv, null, GLib.SpawnFlags.SEARCH_PATH, null, out standard_output, out standard_error, out exit_status);

                    if (standard_output != null && standard_output != "") {
                        append_output (standard_output);
                    }
                    if (standard_error != null && standard_error != "") {
                        append_output (standard_error);
                    }
                }
            } catch (Error e) {
                append_output (_("Execution exception: ") + e.message);
            }
        }
    }

    private void on_repeat_toggled () {
        if (repeat_check.active) {
            countdown_label.set_visible (true);
            setup_repeat_timer ();
        } else {
            stop_repeat_timer ();
            countdown_label.set_visible (false);
        }
    }

    private void setup_repeat_timer () {
        stop_repeat_timer ();
        if (repeat_check.active && last_executed_cmd != "") {
            countdown_label.set_visible (true);
            int interval_sec = (int)repeat_spin.value;
            if (interval_sec < 1) interval_sec = 1;
            remaining_seconds = interval_sec;
            countdown_label.set_text ("%d".printf (remaining_seconds));

            uint interval_ms = (uint)(interval_sec * 1000);

            repeat_timer_id = GLib.Timeout.add (interval_ms, () => {
                if (repeat_check.active && last_executed_cmd != "") {
                    execute_command_once (last_executed_cmd);
                    remaining_seconds = (int)repeat_spin.value;
                    countdown_label.set_text ("%d".printf (remaining_seconds));
                    return true;
                }
                repeat_timer_id = 0;
                return false;
            });

            countdown_timer_id = GLib.Timeout.add (1000, () => {
                if (repeat_check.active) {
                    remaining_seconds--;
                    if (remaining_seconds < 0) {
                        remaining_seconds = (int)repeat_spin.value;
                    }
                    countdown_label.set_text ("%d".printf (remaining_seconds));
                    return true;
                }
                countdown_timer_id = 0;
                return false;
            });
        }
    }

    private void stop_repeat_timer () {
        if (repeat_timer_id != 0) {
            GLib.Source.remove (repeat_timer_id);
            repeat_timer_id = 0;
        }
        if (countdown_timer_id != 0) {
            GLib.Source.remove (countdown_timer_id);
            countdown_timer_id = 0;
        }
        countdown_label.set_text ("");
        countdown_label.set_visible (false);
    }

    private void append_output (string text) {
        string formatted_text = text;
        while (formatted_text.has_suffix ("\n") || formatted_text.has_suffix ("\r")) {
            formatted_text = formatted_text.substring (0, formatted_text.length - 1);
        }
        if (formatted_text == "") return;

        Gtk.TextIter end_iter;
        output_buffer.get_end_iter (out end_iter);
        if (output_buffer.get_char_count () > 0) {
            output_buffer.insert (ref end_iter, "\n", -1);
            output_buffer.get_end_iter (out end_iter);
        }
        output_buffer.insert (ref end_iter, formatted_text, -1);
        output_view.scroll_to_mark (output_buffer.get_insert (), 0.0, true, 0.0, 1.0);
    }

    public void load_config () {
        var key_file = new KeyFile ();
        try {
            if (FileUtils.test (config_path, FileTest.EXISTS)) {
                key_file.load_from_file (config_path, KeyFileFlags.NONE);
                if (key_file.has_key ("Theme", "theme_index")) theme_index = (int) key_file.get_integer ("Theme", "theme_index");
                if (key_file.has_key ("Theme", "border_style")) border_style = (int) key_file.get_integer ("Theme", "border_style");
                if (key_file.has_key ("Theme", "design_category")) design_category = (int) key_file.get_integer ("Theme", "design_category");
                if (key_file.has_key ("Theme", "glass_variant")) glass_variant = (int) key_file.get_integer ("Theme", "glass_variant");
                if (key_file.has_key ("Theme", "element_design_category")) element_design_category = (int) key_file.get_integer ("Theme", "element_design_category");
                if (key_file.has_key ("Theme", "element_glass_variant")) element_glass_variant = (int) key_file.get_integer ("Theme", "element_glass_variant");
                if (key_file.has_key ("Theme", "scale")) ui_scale = key_file.get_double ("Theme", "scale");
                if (key_file.has_key ("Theme", "opacity")) window_opacity = key_file.get_double ("Theme", "opacity");
                if (key_file.has_key ("Theme", "text_scale")) text_scale = key_file.get_double ("Theme", "text_scale");
            if (key_file.has_key ("Theme", "bg_opacity")) bg_opacity = key_file.get_double ("Theme", "bg_opacity");
                if (key_file.has_key ("Theme", "text_opacity")) text_opacity = key_file.get_double ("Theme", "text_opacity");
                if (key_file.has_key ("Theme", "border_opacity")) border_opacity = key_file.get_double ("Theme", "border_opacity");
                if (key_file.has_key ("Theme", "element_bg_opacity")) element_bg_opacity = key_file.get_double ("Theme", "element_bg_opacity");
                if (key_file.has_key ("Theme", "element_border_opacity")) element_border_opacity = key_file.get_double ("Theme", "element_border_opacity");
                if (key_file.has_key ("Theme", "text_3d_style")) text_3d_style = (int) key_file.get_integer ("Theme", "text_3d_style");
                if (key_file.has_key ("Theme", "use_text_shadow")) use_text_shadow = key_file.get_boolean ("Theme", "use_text_shadow");
                if (key_file.has_key ("Theme", "text_shadow_style")) text_shadow_style = (int) key_file.get_integer ("Theme", "text_shadow_style");
                if (key_file.has_key ("Theme", "use_custom_border")) use_custom_border = key_file.get_boolean ("Theme", "use_custom_border");
                if (key_file.has_key ("Theme", "custom_border_r")) custom_border_r = key_file.get_double ("Theme", "custom_border_r");
                if (key_file.has_key ("Theme", "custom_border_g")) custom_border_g = key_file.get_double ("Theme", "custom_border_g");
                if (key_file.has_key ("Theme", "custom_border_b")) custom_border_b = key_file.get_double ("Theme", "custom_border_b");
                if (key_file.has_key ("Theme", "use_border_for_primary")) use_border_for_primary = key_file.get_boolean ("Theme", "use_border_for_primary");
                if (key_file.has_key ("Theme", "custom_primary_r")) custom_primary_r = key_file.get_double ("Theme", "custom_primary_r");
                if (key_file.has_key ("Theme", "custom_primary_g")) custom_primary_g = key_file.get_double ("Theme", "custom_primary_g");
                if (key_file.has_key ("Theme", "custom_primary_b")) custom_primary_b = key_file.get_double ("Theme", "custom_primary_b");
                if (key_file.has_key ("Theme", "window_width")) window_width = (int) key_file.get_integer ("Theme", "window_width");
                if (key_file.has_key ("Theme", "window_height")) window_height = (int) key_file.get_integer ("Theme", "window_height");
                if (key_file.has_key ("Theme", "window_type_hint_mode")) window_type_hint_mode = (int) key_file.get_integer ("Theme", "window_type_hint_mode");
                if (key_file.has_key ("Theme", "window_layer")) window_layer = key_file.get_string ("Theme", "window_layer");
                if (key_file.has_key ("Theme", "window_sticky")) window_sticky = key_file.get_boolean ("Theme", "window_sticky");
                if (key_file.has_key ("Theme", "has_saved_position")) has_saved_position = key_file.get_boolean ("Theme", "has_saved_position");
                if (key_file.has_key ("Theme", "saved_pos_x")) saved_pos_x = (int) key_file.get_integer ("Theme", "saved_pos_x");
                if (key_file.has_key ("Theme", "saved_pos_y")) saved_pos_y = (int) key_file.get_integer ("Theme", "saved_pos_y");
            }
        } catch (Error e) {}
    }

    public void save_config () {
        var key_file = new KeyFile ();
        try {
            key_file.set_integer ("Theme", "theme_index", theme_index);
            key_file.set_integer ("Theme", "border_style", border_style);
            key_file.set_integer ("Theme", "design_category", design_category);
            key_file.set_integer ("Theme", "glass_variant", glass_variant);
            key_file.set_integer ("Theme", "element_design_category", element_design_category);
            key_file.set_integer ("Theme", "element_glass_variant", element_glass_variant);
            key_file.set_double ("Theme", "scale", ui_scale);
            key_file.set_double ("Theme", "opacity", window_opacity);
            key_file.set_double ("Theme", "bg_opacity", bg_opacity);
            key_file.set_double ("Theme", "text_opacity", text_opacity);
            key_file.set_double ("Theme", "border_opacity", border_opacity);
            key_file.set_double ("Theme", "element_bg_opacity", element_bg_opacity);
            key_file.set_double ("Theme", "element_border_opacity", element_border_opacity);
            key_file.set_integer ("Theme", "text_3d_style", text_3d_style);
            key_file.set_boolean ("Theme", "use_text_shadow", use_text_shadow);
            key_file.set_integer ("Theme", "text_shadow_style", text_shadow_style);
            key_file.set_boolean ("Theme", "use_custom_border", use_custom_border);
            key_file.set_double ("Theme", "custom_border_r", custom_border_r);
            key_file.set_double ("Theme", "custom_border_g", custom_border_g);
            key_file.set_double ("Theme", "custom_border_b", custom_border_b);
            key_file.set_boolean ("Theme", "use_border_for_primary", use_border_for_primary);
            key_file.set_double ("Theme", "custom_primary_r", custom_primary_r);
            key_file.set_double ("Theme", "custom_primary_g", custom_primary_g);
            key_file.set_double ("Theme", "custom_primary_b", custom_primary_b);
            key_file.set_integer ("Theme", "window_width", window_width);
            key_file.set_integer ("Theme", "window_height", window_height);
            key_file.set_integer ("Theme", "window_type_hint_mode", window_type_hint_mode);
            key_file.set_string ("Theme", "window_layer", window_layer);
            key_file.set_boolean ("Theme", "window_sticky", window_sticky);
            key_file.set_boolean ("Theme", "has_saved_position", has_saved_position);
            key_file.set_integer ("Theme", "saved_pos_x", saved_pos_x);
            key_file.set_integer ("Theme", "saved_pos_y", saved_pos_y);
            string data = key_file.to_data ();
            FileUtils.set_contents (config_path, data);
        } catch (Error e) {}
    }

    public void load_history () {
        try {
            if (FileUtils.test (history_path, FileTest.EXISTS)) {
                string content;
                FileUtils.get_contents (history_path, out content);
                string[] lines = content.split ("\n");
                foreach (var line in lines) {
                    string trimmed = line.strip ();
                    if (trimmed != "") {
                        string[] filtered = {};
                        foreach (var h in history) {
                            if (h != trimmed) filtered += h;
                        }
                        filtered += trimmed;
                        history = filtered;
                    }
                }
            }
        } catch (Error e) {}
    }

    public void save_history () {
        try {
            string content = string.joinv ("\n", history);
            FileUtils.set_contents (history_path, content);
        } catch (Error e) {}
    }

    private bool on_key_press (Gdk.EventKey event) {
        if (event.keyval == Gdk.Key.Escape) {
            stop_repeat_timer ();
            Gtk.main_quit ();
            return true;
        }
        return false;
    }

    public static int main (string[] args) {
        GLib.Environment.set_prgname ("tech-hud-starter");
        Intl.setlocale (GLib.LocaleCategory.ALL, "");
        if (FileUtils.test ("./locale", FileTest.IS_DIR)) {
            Intl.bindtextdomain ("tech-hud-starter", "./locale");
        } else {
            Intl.bindtextdomain ("tech-hud-starter", "/usr/local/share/locale");
        }
        Intl.textdomain ("tech-hud-starter");

        Gtk.init (ref args);
        var win = new TechHudStarterWindow ();
        win.destroy.connect (Gtk.main_quit);
        win.show_all ();
        Gtk.main ();
        return 0;
    }
}